package cn.iocoder.yudao.module.reading.service.record;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.reading.controller.app.record.vo.ReadingRecordCreateReqVO;
import cn.iocoder.yudao.module.reading.controller.app.record.vo.RecentReadingRespVO;
import cn.iocoder.yudao.module.reading.controller.app.record.vo.TodayReadingRespVO;
import cn.iocoder.yudao.module.reading.controller.app.record.vo.ReadingStatusRespVO;
import cn.iocoder.yudao.module.reading.controller.app.record.vo.ReadingHistoryRespVO;
import cn.iocoder.yudao.module.reading.controller.app.record.vo.ReadingStatsRespVO;
import cn.iocoder.yudao.module.reading.convert.record.ReadingRecordConvert;
import cn.iocoder.yudao.module.reading.dal.dataobject.book.PictureBookDO;
import cn.iocoder.yudao.module.reading.dal.dataobject.bookset.BookSetDO;
import cn.iocoder.yudao.module.reading.dal.dataobject.record.ReadingRecordDO;
import cn.iocoder.yudao.module.reading.dal.mysql.book.PictureBookMapper;
import cn.iocoder.yudao.module.reading.dal.mysql.bookset.BookSetMapper;
import cn.iocoder.yudao.module.reading.dal.mysql.record.ReadingRecordMapper;
import cn.iocoder.yudao.module.reading.dal.mysql.recyclebin.UserRecycleBinMapper;
import cn.iocoder.yudao.module.reading.dal.mysql.hidden.UserHiddenItemsMapper;
import cn.iocoder.yudao.module.reading.dal.dataobject.recyclebin.UserRecycleBinDO;
import cn.iocoder.yudao.module.reading.dal.dataobject.hidden.UserHiddenItemsDO;
import cn.iocoder.yudao.module.reading.service.plan.PlanDailyTaskService;
import cn.iocoder.yudao.module.reading.framework.util.StaticResourceUrlUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import jakarta.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 阅读记录 Service 实现类
 *
 * @author 李晨
 */
@Service
@Validated
@Slf4j
public class ReadingRecordServiceImpl implements ReadingRecordService {

    @Resource
    private ReadingRecordMapper readingRecordMapper;
    @Resource
    private PictureBookMapper pictureBookMapper;
    @Resource
    private BookSetMapper bookSetMapper;
    @Resource
    private UserRecycleBinMapper userRecycleBinMapper;
    @Resource
    private UserHiddenItemsMapper userHiddenItemsMapper;
    @Resource
    private PlanDailyTaskService planDailyTaskService;
    @Resource
    private StaticResourceUrlUtils staticResourceUrlUtils;

    @Override
    public Long createOrUpdateReadingRecord(Long userId, ReadingRecordCreateReqVO createReqVO) {
        // 查询是否已存在记录
        ReadingRecordDO existingRecord = readingRecordMapper.selectByUserIdAndBookId(userId, createReqVO.getBookId());

        LocalDateTime now = LocalDateTime.now();
        
        if (existingRecord == null) {
            // 创建新记录
            ReadingRecordDO record = ReadingRecordDO.builder()
                    .userId(userId)
                    .bookId(createReqVO.getBookId())
                    .planId(createReqVO.getPlanId())
                    .isCompleted(createReqVO.getIsCompleted())
                    .readingProgress(createReqVO.getReadingProgress())
                    .lastPage(createReqVO.getLastPage())
                    .readingTime(createReqVO.getReadingTime())
                    .readingMode(createReqVO.getReadingMode())
                    .firstReadAt(now)
                    .lastReadAt(now)
                    .completedAt(createReqVO.getIsCompleted() ? now : null)
                    .build();
            
            readingRecordMapper.insert(record);

            // 如果阅读完成且有计划ID，同步更新计划任务状态
            if (createReqVO.getIsCompleted() && createReqVO.getPlanId() != null) {
                syncPlanTaskStatus(userId, createReqVO.getPlanId(), createReqVO.getBookId());
            }

            return record.getId();
        } else {
            // 更新现有记录
            // 保护已完成状态：如果现有记录已完成，不允许将其改回未完成状态
            boolean finalIsCompleted;
            LocalDateTime finalCompletedAt;

            if (existingRecord.getIsCompleted() && !createReqVO.getIsCompleted()) {
                // 现有记录已完成，但新请求要设置为未完成 -> 保持已完成状态
                finalIsCompleted = true;
                finalCompletedAt = existingRecord.getCompletedAt();
                log.info("保护已完成状态：用户ID={}, 绘本ID={}, 保持已完成状态", userId, createReqVO.getBookId());
            } else if (createReqVO.getIsCompleted()) {
                // 新请求要设置为完成 -> 更新为完成状态
                finalIsCompleted = true;
                finalCompletedAt = now;
            } else {
                // 现有记录未完成，新请求也未完成 -> 保持未完成状态
                finalIsCompleted = false;
                finalCompletedAt = existingRecord.getCompletedAt();
            }

            ReadingRecordDO updateObj = ReadingRecordDO.builder()
                    .id(existingRecord.getId())
                    .isCompleted(finalIsCompleted)
                    .readingProgress(createReqVO.getReadingProgress())
                    .lastPage(createReqVO.getLastPage())
                    .readingTime(existingRecord.getReadingTime() + createReqVO.getReadingTime())
                    .readingMode(createReqVO.getReadingMode())
                    .lastReadAt(now)
                    .completedAt(finalCompletedAt)
                    .build();

            readingRecordMapper.updateById(updateObj);

            // 如果阅读完成且有计划ID，同步更新计划任务状态
            if (finalIsCompleted && createReqVO.getPlanId() != null) {
                syncPlanTaskStatus(userId, createReqVO.getPlanId(), createReqVO.getBookId());
            }

            return existingRecord.getId();
        }
    }

    @Override
    public ReadingRecordDO getReadingRecord(Long userId, Long bookId) {
        return readingRecordMapper.selectByUserIdAndBookId(userId, bookId);
    }

    @Override
    public List<RecentReadingRespVO> getRecentReading(Long userId, String language, Integer limit) {
        if (limit == null) {
            limit = 10;
        }
        
        // 获取最近阅读记录
        List<ReadingRecordDO> records = readingRecordMapper.selectRecentByUserId(userId, limit * 3); // 多取一些，后面过滤
        
        if (CollUtil.isEmpty(records)) {
            return new ArrayList<>();
        }
        
        // 获取绘本信息
        List<Long> bookIds = records.stream().map(ReadingRecordDO::getBookId).collect(Collectors.toList());
        List<PictureBookDO> books = pictureBookMapper.selectBatchIds(bookIds);
        Map<Long, PictureBookDO> bookMap = books.stream().collect(Collectors.toMap(PictureBookDO::getId, book -> book));
        
        // 获取绘本集信息
        List<Long> bookSetIds = books.stream().map(PictureBookDO::getBookSetId).distinct().collect(Collectors.toList());
        List<BookSetDO> bookSets = bookSetMapper.selectBatchIds(bookSetIds);
        Map<Long, BookSetDO> bookSetMap = bookSets.stream().collect(Collectors.toMap(BookSetDO::getId, bookSet -> bookSet));
        
        // 按绘本集分组并构建响应
        Map<Long, List<ReadingRecordDO>> recordsByBookSet = records.stream()
                .filter(record -> {
                    PictureBookDO book = bookMap.get(record.getBookId());
                    if (book == null) return false;
                    BookSetDO bookSet = bookSetMap.get(book.getBookSetId());
                    // 过滤掉已删除或未启用的绘本集，以及在回收站中的绘本集
                    return bookSet != null
                            && Boolean.TRUE.equals(bookSet.getIsActive())
                            && (language == null || language.equals(bookSet.getLanguage()))
                            && !isBookSetInRecycleBin(userId, bookSet.getId());
                })
                .collect(Collectors.groupingBy(record -> bookMap.get(record.getBookId()).getBookSetId()));
        
        List<RecentReadingRespVO> result = new ArrayList<>();
        for (Map.Entry<Long, List<ReadingRecordDO>> entry : recordsByBookSet.entrySet()) {
            Long bookSetId = entry.getKey();
            List<ReadingRecordDO> bookSetRecords = entry.getValue();
            BookSetDO bookSet = bookSetMap.get(bookSetId);
            
            if (bookSet == null) continue;
            
            // 计算阅读进度
            LocalDateTime lastReadAt = bookSetRecords.stream()
                    .map(ReadingRecordDO::getLastReadAt)
                    .max(LocalDateTime::compareTo)
                    .orElse(null);
            
            int readBookCount = (int) bookSetRecords.stream()
                    .filter(ReadingRecordDO::getIsCompleted)
                    .count();
            
            double readProgress = bookSet.getBookCount() > 0 ? 
                    (double) readBookCount / bookSet.getBookCount() : 0.0;
            
            RecentReadingRespVO respVO = new RecentReadingRespVO();
            respVO.setBookSetId(bookSetId);
            respVO.setBookSetTitle(bookSet.getTitle());
            respVO.setCover(staticResourceUrlUtils.toFullUrl(bookSet.getCover()));
            respVO.setBookCount(bookSet.getBookCount());
            respVO.setSource(bookSet.getSource());
            respVO.setLastReadAt(lastReadAt);
            respVO.setReadProgress(readProgress);
            respVO.setReadBookCount(readBookCount);

            // 转换URL
            respVO.convertUrls();

            result.add(respVO);
            
            if (result.size() >= limit) {
                break;
            }
        }
        
        return result;
    }

    @Override
    public TodayReadingRespVO getTodayReading(Long userId) {
        LocalDate today = LocalDate.now();
        LocalDateTime startTime = today.atStartOfDay();
        LocalDateTime endTime = today.atTime(LocalTime.MAX);

        // 获取今日阅读记录
        List<ReadingRecordDO> todayRecords = readingRecordMapper.selectByUserIdAndDateRange(userId, startTime, endTime);

        TodayReadingRespVO result = new TodayReadingRespVO();
        result.setReadBookCount(todayRecords.size());
        
        if (CollUtil.isEmpty(todayRecords)) {
            result.setBookList(new ArrayList<>());
            return result;
        }
        
        // 获取绘本信息
        List<Long> bookIds = todayRecords.stream().map(ReadingRecordDO::getBookId).collect(Collectors.toList());
        List<PictureBookDO> books = pictureBookMapper.selectBatchIds(bookIds);
        Map<Long, PictureBookDO> bookMap = books.stream().collect(Collectors.toMap(PictureBookDO::getId, book -> book));
        
        // 构建今日阅读绘本列表
        List<TodayReadingRespVO.TodayBookVO> bookList = todayRecords.stream()
                .map(record -> {
                    PictureBookDO book = bookMap.get(record.getBookId());
                    if (book == null) return null;
                    
                    TodayReadingRespVO.TodayBookVO bookVO = new TodayReadingRespVO.TodayBookVO();
                    bookVO.setId(book.getId());
                    bookVO.setTitle(book.getTitle());
                    bookVO.setCover(staticResourceUrlUtils.toFullUrl(book.getCover()));
                    bookVO.setReadAt(record.getLastReadAt());
                    bookVO.setReadingProgress(record.getReadingProgress());
                    bookVO.setIsCompleted(record.getIsCompleted());
                    return bookVO;
                })
                .filter(bookVO -> bookVO != null)
                .collect(Collectors.toList());
        
        result.setBookList(bookList);
        return result;
    }

    @Override
    public void clearRecentReading(Long userId, String language) {
        // 简化实现：删除所有记录（实际应该根据语言过滤）
        readingRecordMapper.deleteRecentByUserId(userId);
    }

    @Override
    public ReadingStatsVO getReadingStats(Long userId) {
        LocalDate today = LocalDate.now();
        LocalDateTime todayStart = today.atStartOfDay();
        LocalDateTime todayEnd = today.atTime(LocalTime.MAX);
        
        LocalDate weekStart = today.minusDays(6);
        LocalDateTime weekStartTime = weekStart.atStartOfDay();
        
        LocalDate monthStart = today.minusDays(29);
        LocalDateTime monthStartTime = monthStart.atStartOfDay();
        
        // 统计各时间段的阅读数据
        Long totalBooks = readingRecordMapper.countTotalReadBooks(userId);
        Long todayBooks = readingRecordMapper.countTodayReadBooks(userId, todayStart, todayEnd);
        Long weekBooks = readingRecordMapper.countTodayReadBooks(userId, weekStartTime, todayEnd);
        Long monthBooks = readingRecordMapper.countTodayReadBooks(userId, monthStartTime, todayEnd);
        
        return new ReadingStatsVO() {
            @Override
            public Integer getTotalBooks() {
                return totalBooks.intValue();
            }
            
            @Override
            public Integer getTodayBooks() {
                return todayBooks.intValue();
            }
            
            @Override
            public Integer getWeekBooks() {
                return weekBooks.intValue();
            }
            
            @Override
            public Integer getMonthBooks() {
                return monthBooks.intValue();
            }
        };
    }

    @Override
    public ReadingStatsRespVO getReadingStatsDetail(Long userId) {
        // 获取基础统计数据
        ReadingStatsVO basicStats = getReadingStats(userId);

        // 获取总阅读时长
        Integer totalReadingTime = readingRecordMapper.sumReadingTimeByUserId(userId);

        // 获取今日阅读时长
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        LocalDateTime todayEnd = LocalDate.now().atTime(LocalTime.MAX);
        Integer todayReadingTime = readingRecordMapper.sumReadingTimeByUserIdAndDateRange(userId, todayStart, todayEnd);

        // 计算连续阅读天数
        Integer consecutiveDays = calculateConsecutiveDays(userId);
        Integer maxConsecutiveDays = calculateMaxConsecutiveDays(userId);

        // 获取月度统计
        List<ReadingStatsRespVO.MonthlyStatsVO> monthlyStats = getMonthlyStats(userId);

        return ReadingRecordConvert.INSTANCE.convertToStatsRespVO(
                basicStats.getTotalBooks(), basicStats.getTodayBooks(),
                basicStats.getWeekBooks(), basicStats.getMonthBooks(),
                totalReadingTime, todayReadingTime,
                consecutiveDays, maxConsecutiveDays, monthlyStats);
    }

    @Override
    public ReadingStatusRespVO getTodayReadingStatus(Long userId) {
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        LocalDateTime todayEnd = LocalDate.now().atTime(LocalTime.MAX);

        // 获取今日阅读记录
        List<ReadingRecordDO> todayRecords = readingRecordMapper.selectByUserIdAndDateRange(userId, todayStart, todayEnd);

        // 获取今日阅读时长
        Integer todayReadingTime = readingRecordMapper.sumReadingTimeByUserIdAndDateRange(userId, todayStart, todayEnd);

        return ReadingRecordConvert.INSTANCE.convertToStatusRespVO(todayRecords, todayReadingTime);
    }

    @Override
    public List<ReadingHistoryRespVO> getReadingHistory(Long userId, Integer page, Integer size, String lang) {
        // 分页查询阅读记录
        int offset = (page - 1) * size;
        List<ReadingRecordDO> records = readingRecordMapper.selectByUserIdWithPaging(userId, lang, offset, size);

        if (CollUtil.isEmpty(records)) {
            return new ArrayList<>();
        }

        // 获取绘本信息
        List<Long> bookIds = records.stream().map(ReadingRecordDO::getBookId).collect(Collectors.toList());
        Map<Long, PictureBookDO> bookMap = pictureBookMapper.selectByIds(bookIds)
                .stream().collect(Collectors.toMap(PictureBookDO::getId, book -> book));

        // 获取绘本集信息
        List<Long> bookSetIds = bookMap.values().stream()
                .map(PictureBookDO::getBookSetId)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, BookSetDO> bookSetMap = bookSetMapper.selectByIds(bookSetIds)
                .stream().collect(Collectors.toMap(BookSetDO::getId, bookSet -> bookSet));

        // 转换为响应VO，过滤掉已删除或未启用的绘本集
        return records.stream()
                .map(record -> {
                    PictureBookDO book = bookMap.get(record.getBookId());
                    BookSetDO bookSet = book != null ? bookSetMap.get(book.getBookSetId()) : null;
                    return ReadingRecordConvert.INSTANCE.convertToHistoryRespVO(record, book, bookSet);
                })
                .filter(historyVO -> {
                    // 过滤掉绘本集已删除或未启用的记录，以及在回收站中的绘本集
                    if (historyVO.getBookSetId() == null) return true; // 保留没有绘本集信息的记录
                    BookSetDO bookSet = bookSetMap.get(historyVO.getBookSetId());
                    return bookSet != null
                            && Boolean.TRUE.equals(bookSet.getIsActive())
                            && !isBookSetInRecycleBin(userId, bookSet.getId());
                })
                .collect(Collectors.toList());
    }

    @Override
    public void deleteReadingRecord(Long userId, Long recordId) {
        // 校验记录存在且属于当前用户
        ReadingRecordDO record = readingRecordMapper.selectById(recordId);
        if (record == null || !record.getUserId().equals(userId)) {
            throw new RuntimeException("阅读记录不存在或无权限删除");
        }

        // 软删除记录
        readingRecordMapper.deleteById(recordId);

        log.info("删除阅读记录成功，用户ID: {}, 记录ID: {}", userId, recordId);
    }

    @Override
    public void clearAllReadingRecords(Long userId) {
        // 删除用户所有阅读记录
        int deletedCount = readingRecordMapper.deleteByUserId(userId);

        log.info("清空所有阅读记录成功，用户ID: {}, 删除数量: {}", userId, deletedCount);
    }

    /**
     * 计算连续阅读天数
     */
    private Integer calculateConsecutiveDays(Long userId) {
        // TODO: 实现连续阅读天数计算逻辑
        return 0;
    }

    /**
     * 计算最长连续阅读天数
     */
    private Integer calculateMaxConsecutiveDays(Long userId) {
        // TODO: 实现最长连续阅读天数计算逻辑
        return 0;
    }

    /**
     * 获取月度统计数据
     */
    private List<ReadingStatsRespVO.MonthlyStatsVO> getMonthlyStats(Long userId) {
        // TODO: 实现月度统计数据获取逻辑
        return new ArrayList<>();
    }

    /**
     * 同步计划任务状态
     * 当用户完成阅读时，自动将对应的计划任务标记为完成
     */
    private void syncPlanTaskStatus(Long userId, Long planId, Long bookId) {
        try {
            // 查找对应的计划任务并标记为完成
            planDailyTaskService.completeTaskByBookId(userId, planId, bookId);
            log.info("同步计划任务状态成功，用户ID: {}, 计划ID: {}, 绘本ID: {}", userId, planId, bookId);
        } catch (Exception e) {
            log.error("同步计划任务状态失败，用户ID: {}, 计划ID: {}, 绘本ID: {}", userId, planId, bookId, e);
            // 不抛出异常，避免影响阅读记录的保存
        }
    }

    /**
     * 过滤用户回收站中的绘本集
     */
    private boolean isBookSetInRecycleBin(Long userId, Long bookSetId) {
        if (userId == null || bookSetId == null) {
            return false;
        }

        // 获取用户回收站中的绘本集ID列表
        List<UserRecycleBinDO> recycleBinList = userRecycleBinMapper.selectListByUserId(userId);
        java.util.Set<Long> recycleBinBookSetIds = recycleBinList.stream()
                .filter(item -> "book_set".equals(item.getItemType()))
                .map(UserRecycleBinDO::getItemId)
                .collect(java.util.stream.Collectors.toSet());

        // 获取用户隐藏的绘本集ID列表
        List<UserHiddenItemsDO> hiddenItemsList = userHiddenItemsMapper.selectListByUserIdAndType(userId, "book_set");
        java.util.Set<Long> hiddenBookSetIds = hiddenItemsList.stream()
                .map(UserHiddenItemsDO::getItemId)
                .collect(java.util.stream.Collectors.toSet());

        // 检查绘本集是否在回收站或隐藏列表中
        return recycleBinBookSetIds.contains(bookSetId) || hiddenBookSetIds.contains(bookSetId);
    }

}
